home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / tcl / dist6.3 / tclAssem.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-09-23  |  5.7 KB  |  207 lines

  1. /* 
  2.  * tclAssem.c --
  3.  *
  4.  *    This file contains procedures to help assemble Tcl commands
  5.  *    from an input source  where commands may arrive in pieces, e.g.
  6.  *    several lines of type-in corresponding to one command.
  7.  *
  8.  * Copyright 1990-1991 Regents of the University of California
  9.  * Permission to use, copy, modify, and distribute this
  10.  * software and its documentation for any purpose and without
  11.  * fee is hereby granted, provided that the above copyright
  12.  * notice appear in all copies.  The University of California
  13.  * makes no representations about the suitability of this
  14.  * software for any purpose.  It is provided "as is" without
  15.  * express or implied warranty.
  16.  */
  17.  
  18. #ifndef lint
  19. static char rcsid[] = "$Header: /sprite/src/lib/tcl/RCS/tclAssem.c,v 1.8 91/09/23 11:22:22 ouster Exp $ SPRITE (Berkeley)";
  20. #endif /* not lint */
  21.  
  22. #include "tclInt.h"
  23.  
  24. /*
  25.  * The structure below is the internal representation for a command
  26.  * buffer, which is used to hold a piece of a command until a full
  27.  * command is available.  When a full command is available, it will
  28.  * be returned to the user, but it will also be retained in the buffer
  29.  * until the NEXT call to Tcl_AssembleCmd, at which point it will be
  30.  * removed.
  31.  */
  32.  
  33. typedef struct {
  34.     char *buffer;        /* Storage for command being assembled.
  35.                  * Malloc-ed, and grows as needed. */
  36.     int bufSize;        /* Total number of bytes in buffer. */
  37.     int bytesUsed;        /* Number of bytes in buffer currently
  38.                  * occupied (0 means there is not a
  39.                  * buffered incomplete command). */
  40. } CmdBuf;
  41.  
  42. /*
  43.  * Default amount of space to allocate in command buffer:
  44.  */
  45.  
  46. #define CMD_BUF_SIZE 100
  47.  
  48. /*
  49.  *----------------------------------------------------------------------
  50.  *
  51.  * Tcl_CreateCmdBuf --
  52.  *
  53.  *    Allocate and initialize a command buffer.
  54.  *
  55.  * Results:
  56.  *    The return value is a token that may be passed to
  57.  *    Tcl_AssembleCmd and Tcl_DeleteCmdBuf.
  58.  *
  59.  * Side effects:
  60.  *    Memory is allocated.
  61.  *
  62.  *----------------------------------------------------------------------
  63.  */
  64.  
  65. Tcl_CmdBuf
  66. Tcl_CreateCmdBuf()
  67. {
  68.     register CmdBuf *cbPtr;
  69.  
  70.     cbPtr = (CmdBuf *) ckalloc(sizeof(CmdBuf));
  71.     cbPtr->buffer = (char *) ckalloc(CMD_BUF_SIZE);
  72.     cbPtr->bufSize = CMD_BUF_SIZE;
  73.     cbPtr->bytesUsed = 0;
  74.     return (Tcl_CmdBuf) cbPtr;
  75. }
  76.  
  77. /*
  78.  *----------------------------------------------------------------------
  79.  *
  80.  * Tcl_DeleteCmdBuf --
  81.  *
  82.  *    Release all of the resources associated with a command buffer.
  83.  *    The caller should never again use buffer again.
  84.  *
  85.  * Results:
  86.  *    None.
  87.  *
  88.  * Side effects:
  89.  *    Memory is released.
  90.  *
  91.  *----------------------------------------------------------------------
  92.  */
  93.  
  94. void
  95. Tcl_DeleteCmdBuf(buffer)
  96.     Tcl_CmdBuf buffer;        /* Token for command buffer (return value
  97.                  * from previous call to Tcl_CreateCmdBuf). */
  98. {
  99.     register CmdBuf *cbPtr = (CmdBuf *) buffer;
  100.  
  101.     ckfree(cbPtr->buffer);
  102.     ckfree((char *) cbPtr);
  103. }
  104.  
  105. /*
  106.  *----------------------------------------------------------------------
  107.  *
  108.  * Tcl_AssembleCmd --
  109.  *
  110.  *    This is a utility procedure to assist in situations where
  111.  *    commands may be read piece-meal from some input source.  Given
  112.  *    some input text, it adds the text to an input buffer and returns
  113.  *    whole commands when they are ready.
  114.  *
  115.  * Results:
  116.  *    If the addition of string to any currently-buffered information
  117.  *    results in one or more complete Tcl commands, then the return value
  118.  *    is a pointer to the complete command(s).  The command value will
  119.  *    only be valid until the next call to this procedure with the
  120.  *    same buffer.  If the addition of string leaves an incomplete
  121.  *    command at the end of the buffer, then NULL is returned.
  122.  *
  123.  * Side effects:
  124.  *    If string leaves a command incomplete, the partial command
  125.  *    information is buffered for use in later calls to this procedure.
  126.  *    Once a command has been returned, that command is deleted from
  127.  *    the buffer on the next call to this procedure.
  128.  *
  129.  *----------------------------------------------------------------------
  130.  */
  131.  
  132. char *
  133. Tcl_AssembleCmd(buffer, string)
  134.     Tcl_CmdBuf buffer;        /* Token for a command buffer previously
  135.                  * created by Tcl_CreateCmdBuf.  */
  136.     char *string;        /* Bytes to be appended to command stream.
  137.                  * Note:  if the string is zero length,
  138.                  * then whatever is buffered will be
  139.                  * considered to be a complete command
  140.                  * regardless of whether parentheses are
  141.                  * matched or not. */
  142. {
  143.     register CmdBuf *cbPtr = (CmdBuf *) buffer;
  144.     int length, totalLength;
  145.     register char *p;
  146.  
  147.     /*
  148.      * If an empty string is passed in, just pretend the current
  149.      * command is complete, whether it really is or not.
  150.      */
  151.  
  152.     length = strlen(string);
  153.     if (length == 0) {
  154.     cbPtr->bytesUsed = 0;
  155.     return cbPtr->buffer;
  156.     }
  157.  
  158.     /*
  159.      * Add the new information to the buffer.  If the current buffer
  160.      * isn't large enough, grow it by at least a factor of two, or
  161.      * enough to hold the new text.
  162.      */
  163.  
  164.     length = strlen(string);
  165.     totalLength = cbPtr->bytesUsed + length + 1;
  166.     if (totalLength > cbPtr->bufSize) {
  167.     unsigned int newSize;
  168.     char *newBuf;
  169.  
  170.     newSize = cbPtr->bufSize*2;
  171.     if (newSize < totalLength) {
  172.         newSize = totalLength;
  173.     }
  174.     newBuf = (char *) ckalloc(newSize);
  175.     strcpy(newBuf, cbPtr->buffer);
  176.     ckfree(cbPtr->buffer);
  177.     cbPtr->buffer = newBuf;
  178.     cbPtr->bufSize = newSize;
  179.     }
  180.     strcpy(cbPtr->buffer+cbPtr->bytesUsed, string);
  181.     cbPtr->bytesUsed += length;
  182.  
  183.     /*
  184.      * See if there is now a complete command in the buffer.
  185.      */
  186.  
  187.     p = cbPtr->buffer;
  188.     while (1) {
  189.     int gotNewLine = 0;
  190.  
  191.     while (isspace(*p)) {
  192.         if (*p == '\n') {
  193.         gotNewLine = 1;
  194.         }
  195.         p++;
  196.     }
  197.     if (*p == 0) {
  198.         if (gotNewLine) {
  199.         cbPtr->bytesUsed = 0;
  200.         return cbPtr->buffer;
  201.         }
  202.         return NULL;
  203.     }
  204.     p = TclWordEnd(p, 0);
  205.     }
  206. }
  207.